export enum EachReturn {
  DELETE,
  BREAK,
  DELETE_AND_BREAK,
}

export function eachArray<T>(target: T[], callback: (value: T, index: number) => EachReturn | void) {
  for (let index = 0; index < target.length; index++) {
    const result = callback(target[index], index)
    if (result === EachReturn.DELETE) {
      target.splice(index--, 1)
    } else if (result === EachReturn.DELETE_AND_BREAK) {
      target.splice(index--, 1)
      break
    } else if (result === EachReturn.BREAK) {
      break
    }
  }
}

export function eachObject<T>(target: { [propName: string]: T }, callback: (value: T, key: string) => EachReturn | void) {
  for (let key in target) {
    const result = Reflect.apply(callback, target, [target[key], key])
    if (result === EachReturn.DELETE) {
      Reflect.deleteProperty(target, key)
    } else if (result === EachReturn.DELETE_AND_BREAK) {
      Reflect.deleteProperty(target, key)
      break
    } else if (result === EachReturn.BREAK) {
      break
    }
  }
}

/**
 *
 * HTML 字符串换 DOM
 * @param html HTML 字符串
 * @param allowTextNode 子节点中允许包含 TextNode 节点
 * @returns
 */
export function htmlToDom(html: string, allowTextNode?: boolean) {
  const div = document.createElement('div')
  div.innerHTML = html
  const fragment = document.createDocumentFragment()
  Array.from(allowTextNode ? div.childNodes : div.children).forEach((node) => {
    fragment.append(node)
  })
  return fragment
}

export const UUID = /^[a-zA-Z][a-zA-Z0-9]*$/

/**
 * 生成唯一的 id attribute value
 * @param lenth 随机字符串的有效长度（有效长度 = 总长度 - 前缀长度）
 * @param prefix 随机字符串的前缀
 * @returns
 */
export function uuid(lenth: number = 4, prefix?: string) {
  lenth = lenth < 1 ? 1 : lenth > 12 ? 12 : lenth
  prefix = prefix && UUID.test(prefix) ? prefix : 'pe'
  return Math.random()
    .toString(16)
    .replace('0.', prefix)
    .slice(0, lenth + prefix.length)
}

/**
 * 执行某个对象上未知定义的方法
 * @param target
 * @param callback
 * @param thisArg
 * @param args
 */
// export function callback<T extends object, K extends object>(target: T, callback: string, thisArg: T | K | null, ...args: any[]) {
//   const cb = Reflect.get(target, callback)
//   if (typeof cb === 'function') {
//     Reflect.apply(cb, thisArg || target, args)
//   }
// }
